<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <h1>查看原型对象</h1>
    <p>原型：用于描述类的模样，表名类上有什么属性。</p>
    <p>原型对象：所有的构造方法都有prototype属性，指向构造方法的原型对象。所有的对象也有__proto__属性，用于指向它的构造方法（类）的prototype属性。</p>
    <p>原型链：最终会归一到Object.prototype。</p>
    <p>访问对象的属性，会现在自己的原型上去获取属性，如果没有找到那么向上找继续寻找原型的属性，如果最终没有找到返回undefined。</p>
    <ul>
        <li>prototype：构造函数（类）使用prototype访问原型对象。</li>
        <li>__proto__：对象使用__proto__访问原型对象。</li>
    </ul>
    <h2>作业</h2>
    <dl>
        <dt>必做</dt>
        <dd>利用原型链，在Date类上挂载序列化时间对象的方法，按照"2022-04-01 23:23:23"的字符串形式返回当前时间值。</dd>
    </dl>
    <script>
        // ES5的构造方法
        function Student(name, age) {
            this.name = name;
            this.age = age;
        }
        // 通过构造方法，创建对象。
        let stu = new Student();

        // 类名（构造方法）访问原型对象
        let p1 = Student.prototype;
        // 对象访问原型对象
        let p2 = stu.__proto__;

        console.log("p1 === p2：", p1 === p2); // true

        // 挂载属性
        p1.school = "知了堂";
        p1.sayHello = function () {
            console.log("欢迎来学习");
        }
        console.log("stu.school = ", stu.school);
        stu.sayHello();

        // 判断p1是不是一个对象
        console.log(p1 instanceof Object);  // true
        // p1或者p2是原型“对象”，那么按刚才的结论，对象可以使用__proto__属性，继续寻找原型对象。
        console.log("p1 = ", p1); // Stduent()
        // 于是继续获取原型对象
        let p3 = p1.__proto__;
        console.log("p3 = ", p3); // Object()

        let p4 = Object.prototype;
        // 所有对象（或者类）的原型对象，最终都指向到了Object的prototype中
        console.log("p3 === p4：",p3 === p4); // true

        Object.prototype.sayBye = function() {
            console.log("Goodbye:",this.name);
        }

        stu.sayBye();

        console.log(Student.prototype.age); // undefined
        console.log(Student.prototype.school); // "知了堂"
    </script>
</body>

</html>